package com.jwong.client.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

import javax.servlet.http.HttpServletResponse;

@Slf4j
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_SERVER_ID = "user-server-resource";

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter: off
        http
            .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> {
                    //不负责身份验证，如果请求被PreAuthenticatedProcessingFilter拒绝，则调用方法的实现
                    if (log.isDebugEnabled()) {
                        log.debug("Pre-authenticated entry point called. Rejecting access. The path : {}, remote host: {}",
                                request.getPathInfo(), request.getRemoteHost());
                    }
                    response.sendError(HttpServletResponse.SC_FORBIDDEN, "没有权限，拒绝访问！");
                })
            .and()
                .authorizeRequests()
                .antMatchers("/login**", "/sms-login**", "/sms-code/**" ,"/sms-code/voice/**", "/smsCode/conform**", "/users/password**").permitAll()
                .antMatchers("/actuator/**").permitAll()
                // 服务账号访问端点控制
                //.requestMatchers(EndpointRequest.toAnyEndpoint()).access("#oauth2.hasAnyScope('endpoint_read') and hasRole('SERVICE_ACCOUNT')")
                // 访问该服务下的接口必须拥有的任一scope和任一role，粗粒度的控制
                .anyRequest().access("#oauth2.hasAnyScope('write', 'read') and hasAnyRole('USER', 'SCHOOL_ADMIN', 'SUPER_ADMIN')")
            .and()
                .csrf()
                .disable()
        ;
        // @formatter: on
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(RESOURCE_SERVER_ID)
                .stateless(true);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Configuration
    static class SwaggerSecurity extends WebSecurityConfigurerAdapter {

        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
                            "/swagger-resources","/swagger-resources/configuration/security",
                            "/swagger-ui.html", "/webjars/**", "**/favicon.ico"
                    );
        }

    }

}
